package com.example.lets;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.Toast;
import android.widget.ZoomControls;
import android.widget.AdapterView.OnItemSelectedListener;

import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BitmapDescriptor;
import com.baidu.mapapi.map.BitmapDescriptorFactory;
import com.baidu.mapapi.map.MapPoi;
import com.baidu.mapapi.map.MapStatus;
import com.baidu.mapapi.map.MapStatusUpdate;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.Marker;
import com.baidu.mapapi.map.MarkerOptions;
import com.baidu.mapapi.map.MyLocationConfiguration;
import com.baidu.mapapi.map.BaiduMap.OnMapClickListener;
import com.baidu.mapapi.map.BaiduMap.OnMapDoubleClickListener;
import com.baidu.mapapi.map.BaiduMap.OnMapLongClickListener;
import com.baidu.mapapi.map.BaiduMap.OnMapTouchListener;
import com.baidu.mapapi.map.MarkerOptions.MarkerAnimateType;
import com.baidu.mapapi.map.MyLocationConfiguration.LocationMode;
import com.baidu.mapapi.map.MyLocationData;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.model.inner.GeoPoint;
import com.baidu.mapapi.model.inner.Point;
import com.baidu.mapapi.overlayutil.PoiOverlay;
import com.baidu.mapapi.search.core.CityInfo;
import com.baidu.mapapi.search.core.PoiInfo;
import com.baidu.mapapi.search.core.SearchResult;
import com.baidu.mapapi.search.geocode.GeoCodeResult;
import com.baidu.mapapi.search.geocode.GeoCoder;
import com.baidu.mapapi.search.geocode.OnGetGeoCoderResultListener;
import com.baidu.mapapi.search.geocode.ReverseGeoCodeOption;
import com.baidu.mapapi.search.geocode.ReverseGeoCodeResult;
import com.baidu.mapapi.search.geocode.ReverseGeoCodeResult.AddressComponent;
import com.baidu.mapapi.search.poi.OnGetPoiSearchResultListener;
import com.baidu.mapapi.search.poi.PoiCitySearchOption;
import com.baidu.mapapi.search.poi.PoiDetailResult;
import com.baidu.mapapi.search.poi.PoiDetailSearchOption;
import com.baidu.mapapi.search.poi.PoiNearbySearchOption;
import com.baidu.mapapi.search.poi.PoiResult;
import com.baidu.mapapi.search.poi.PoiSearch;
import com.baidu.mapapi.search.sug.OnGetSuggestionResultListener;
import com.baidu.mapapi.search.sug.SuggestionResult;
import com.baidu.mapapi.search.sug.SuggestionSearch;
import com.baidu.mapapi.search.sug.SuggestionSearchOption;


public class BaiduMapActivity extends Activity implements
		OnGetPoiSearchResultListener, OnGetSuggestionResultListener,
		OnGetGeoCoderResultListener {

	private PoiSearch mPoiSearch = null;
	private SuggestionSearch mSuggestionSearch = null;
	private BaiduMap mBaiduMap = null;
	private MapView mMapView = null;
	/**
	 * 搜索关键字输入窗口
	 */
	private AutoCompleteTextView keyWorldsView = null;
	private EditText curLoc = null;
	private ArrayAdapter<String> sugAdapter = null;
	private int load_Index = 0;
	private Spinner searchRegion = null;
	private boolean searchInCity = false;
	
	// 定位相关
	BitmapDescriptor mCurrentMarker;
	LocationClient mLocClient;
	private MyLocationListenner myListener = new MyLocationListenner();
	private String address = null;
	private String detailAddress = null;
	private AddressComponent ac = null;
	private LatLng curLl = null;
	private GeoCoder mSearch = null;
	
	// 标志
	private Marker myMarker = null;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_baidumap);
		// 初始化搜索模块，注册搜索事件监听
		mPoiSearch = PoiSearch.newInstance();
		mPoiSearch.setOnGetPoiSearchResultListener(this);
		mSuggestionSearch = SuggestionSearch.newInstance();
		mSuggestionSearch.setOnGetSuggestionResultListener(this);
		keyWorldsView = (AutoCompleteTextView) findViewById(R.id.baidumap_searchKey);
		curLoc = (EditText) findViewById(R.id.baidumap_curloc);
		sugAdapter = new ArrayAdapter<String>(this,
				android.R.layout.simple_dropdown_item_1line);
		keyWorldsView.setAdapter(sugAdapter);
		
		mMapView = (MapView) findViewById(R.id.baidumap_view);
		mBaiduMap = mMapView.getMap();

		detailAddress = "";

		// 设置Spinner显示内容
		searchRegion = (Spinner) findViewById(R.id.baidumap_searchRegion);
		String[] items = {"周边", "本市"};
		final ArrayAdapter aa = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, items);
		aa.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
		searchRegion.setAdapter(aa);
	
		// 设定定位模式为普通
        mBaiduMap
                .setMyLocationConfigeration(new MyLocationConfiguration(
                		LocationMode.NORMAL, true, mCurrentMarker));
        
        // 移除默认的百度LOGO&缩放按钮
        View child = mMapView.getChildAt(1);
        // 隐藏百度logo和缩放控件ZoomControl
        if (child instanceof ImageView || child instanceof ZoomControls ) {
        	child.setVisibility(View.INVISIBLE);
        }
		
		// 开启定位图层
		mBaiduMap.setMyLocationEnabled(true);
		
		// 定位初始化
		mLocClient = new LocationClient(this);
		mLocClient.registerLocationListener(myListener);
		LocationClientOption option = new LocationClientOption();
		option.setOpenGps(true);// 打开gps
		option.setCoorType("bd09ll"); // 设置坐标类型
		option.setScanSpan(0);
		mLocClient.setLocOption(option);
		mLocClient.start();
		
		// 初始化查询模块
		mSearch = GeoCoder.newInstance();
		mSearch.setOnGetGeoCodeResultListener(this);
		
		// 初始化地图点击事件
		initListener();
		
		/**
		 * 当输入关键字变化时，动态更新建议列表
		 */
		keyWorldsView.addTextChangedListener(new TextWatcher() {

			@Override
			public void afterTextChanged(Editable arg0) {

			}

			@Override
			public void beforeTextChanged(CharSequence arg0, int arg1,
					int arg2, int arg3) {

			}

			@Override
			public void onTextChanged(CharSequence cs, int arg1, int arg2,
					int arg3) {
				if (cs.length() <= 0 || ac == null) {
					return;
				}
				/**
				 * 使用建议搜索服务获取建议列表，结果在onSuggestionResult()中更新
				 */
				mSuggestionSearch
						.requestSuggestion((new SuggestionSearchOption())
								.keyword(cs.toString()).city(ac.city));
			}
		});
		
		searchRegion.setOnItemSelectedListener(new OnItemSelectedListener(){

			@Override
			public void onItemSelected(AdapterView<?> parent, View view,
					int position, long id) {
				searchInCity = position == 1;
			}

			@Override
			public void onNothingSelected(AdapterView<?> parent) {
				// TODO Auto-generated method stub
			}
			
		});

		Button confirm = (Button) this.findViewById(R.id.baidumap_confirmAddress);
		confirm.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				String baseAddress = curLoc.getText().toString();
				if (baseAddress == null || baseAddress.equals("")) {
					Toast.makeText(BaiduMapActivity.this, "基础地址不存在！请重新选择！", Toast.LENGTH_LONG)
							.show();
					return;
				}
				Intent intent = new Intent();
				intent.putExtra("baseAddress", address);
				intent.putExtra("detailAddress", detailAddress);
				setResult(RESULT_OK, intent);
				BaiduMapActivity.this.finish();
			}
		});
		
		Button relocate = (Button) this.findViewById(R.id.baidumap_relocate);
		relocate.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				mBaiduMap.clear();
				mLocClient.stop();
				mLocClient.start();
			}
		});
	}
	
	/**
	 * 定位SDK监听函数
	 */
	public class MyLocationListenner implements BDLocationListener {

        @Override
        public void onReceiveLocation(BDLocation location) {

			ac = null;

            // map view 销毁后不在处理新接收的位置
            if (location == null || mMapView == null) {
            	Toast.makeText(BaiduMapActivity.this, "定位服务未开启！", Toast.LENGTH_SHORT).show();
                return;
            }
            int type = location.getLocType();
            if (type != 61 && type != 65 && type != 66 && type != 68 && type != 161) {
            	switch (type) {
            	case 62: Toast.makeText(BaiduMapActivity.this, "扫描整合定位依据失败，定位结果无效", Toast.LENGTH_SHORT).show();
            			 break;
            	case 63: Toast.makeText(BaiduMapActivity.this, "网络异常，定位失败", Toast.LENGTH_SHORT).show();
            			 break;
            	case 67: Toast.makeText(BaiduMapActivity.this, "离线定位失败", Toast.LENGTH_SHORT).show();
            			 break;
            	default: Toast.makeText(BaiduMapActivity.this, "服务端异常，定位失败", Toast.LENGTH_SHORT).show();
            	}
            	return;
            }

			curLl = new LatLng(location.getLatitude(),
					location.getLongitude());
			//MapStatusUpdate u = MapStatusUpdateFactory.newLatLng(curLl);
			//mBaiduMap.setMapStatus(u);
			//mBaiduMap.setMapStatus(MapStatusUpdateFactory.zoomTo(18));
			//mBaiduMap.animateMapStatus(u, 50);
			//mBaiduMap.animateMapStatus(MapStatusUpdateFactory.zoomTo(18));

			MapStatus mMapStatus = new MapStatus.Builder()
					.target(curLl)
					.zoom(18)
					.build();
			MapStatusUpdate mMapStatusUpdate = MapStatusUpdateFactory.newMapStatus(mMapStatus);
			mBaiduMap.animateMapStatus(mMapStatusUpdate);
/*
			MapStatusUpdate u = MapStatusUpdateFactory.newLatLng(curLl);
			mBaiduMap.animateMapStatus(u);
			mBaiduMap.animateMapStatus(MapStatusUpdateFactory.zoomTo(18));*/

            MarkerOptions mo = new MarkerOptions().position(curLl).icon(
            		BitmapDescriptorFactory.fromResource(R.drawable.icon_marka))
    				.zIndex(9).draggable(false);
            mo.animateType(MarkerAnimateType.drop);
            myMarker = (Marker) mBaiduMap.addOverlay(mo);

            // 获取当前位置的地址
            mSearch.reverseGeoCode(new ReverseGeoCodeOption()
			.location(curLl));
        }

		public void onReceivePoi(BDLocation poiLocation) {
		}
	}
	
	private void initListener() {
		
		mBaiduMap.setOnMapTouchListener(new OnMapTouchListener() {
			
			@Override
			public void onTouch(MotionEvent event) {
				
			}
		});
		
		mBaiduMap.setOnMapClickListener(new OnMapClickListener() {
			
			public void onMapClick(LatLng point) {

				ac = null;
				// 更新当前位置
				curLl = point;
				
				mBaiduMap.clear();
				// 在点击位置生成新的Marker
                MarkerOptions mo = new MarkerOptions().position(point).icon(
                		BitmapDescriptorFactory.fromResource(R.drawable.icon_marka))
        				.zIndex(9).draggable(false);
                mo.animateType(MarkerAnimateType.grow);
                myMarker = (Marker) mBaiduMap.addOverlay(mo);
                
                MapStatusUpdate u = MapStatusUpdateFactory.newLatLng(point);
                mBaiduMap.animateMapStatus(u, 100);
                
                // 获取点击位置的地址
                mSearch.reverseGeoCode(new ReverseGeoCodeOption()
				.location(point));
			}

			public boolean onMapPoiClick(MapPoi poi) {
				ac = null;
				// 更新当前位置
				LatLng point = poi.getPosition();
				curLl = point;

				mBaiduMap.clear();
				// 在点击位置生成新的Marker
				MarkerOptions mo = new MarkerOptions().position(point).icon(
						BitmapDescriptorFactory.fromResource(R.drawable.icon_marka))
						.zIndex(9).draggable(false);
				mo.animateType(MarkerAnimateType.grow);
				myMarker = (Marker) mBaiduMap.addOverlay(mo);

				MapStatusUpdate u = MapStatusUpdateFactory.newLatLng(point);
				mBaiduMap.animateMapStatus(u, 100);

				// 获取点击位置的地址
				mSearch.reverseGeoCode(new ReverseGeoCodeOption()
						.location(point));
				return false;
			}
		});
		
		mBaiduMap.setOnMapLongClickListener(new OnMapLongClickListener() {
			public void onMapLongClick(LatLng point) {
				
			}
		});
		
		mBaiduMap.setOnMapDoubleClickListener(new OnMapDoubleClickListener() {
			public void onMapDoubleClick(LatLng point) {

			}
		});
	}

	@Override
	protected void onPause() {
		super.onPause();
	}

	@Override
	protected void onResume() {
		super.onResume();
	}

	@Override
	protected void onDestroy() {
		mPoiSearch.destroy();
		mSuggestionSearch.destroy();
		// 退出时销毁定位
		mLocClient.stop();
		// 关闭定位图层
		mBaiduMap.setMyLocationEnabled(false);
		mMapView.onDestroy();
		mMapView = null;
		super.onDestroy();
	}

	@Override
	protected void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);
	}

	@Override
	protected void onRestoreInstanceState(Bundle savedInstanceState) {
		super.onRestoreInstanceState(savedInstanceState);
	}

	/**
	 * 影响搜索按钮点击事件
	 * 
	 * @param v
	 */
	public void searchButtonProcess(View v) {
		if (ac == null) return;
		
		if (searchInCity) {
			mPoiSearch.searchInCity((new PoiCitySearchOption())
					.city(ac.city)
					.keyword(keyWorldsView.getText().toString())
					.pageNum(load_Index));
		} else {
			if (curLl == null) {
				Toast.makeText(this, "定位失败！无法进行周边搜索！", Toast.LENGTH_SHORT).show();
				return;
			}
			mPoiSearch.searchNearby((new PoiNearbySearchOption())
					.location(curLl)
					.radius(2000)
					.keyword(keyWorldsView.getText().toString())
					.pageNum(load_Index));
		}
	}

	public void goToNextPage(View v) {
		load_Index++;
		searchButtonProcess(null);
	}

	public void onGetPoiResult(PoiResult result) {
		if (result == null
				|| result.error == SearchResult.ERRORNO.RESULT_NOT_FOUND) {
			Toast.makeText(BaiduMapActivity.this, "未找到结果", Toast.LENGTH_LONG)
			.show();
			return;
		}
		if (result.error == SearchResult.ERRORNO.NO_ERROR) {
			mBaiduMap.clear();
			PoiOverlay overlay = new MyPoiOverlay(mBaiduMap);
			mBaiduMap.setOnMarkerClickListener(overlay);
			overlay.setData(result);
			overlay.addToMap();
			overlay.zoomToSpan();
			return;
		}
		if (result.error == SearchResult.ERRORNO.AMBIGUOUS_KEYWORD) {

			// 当输入关键字在本市没有找到，但在其他城市找到时，返回包含该关键字信息的城市列表
			String strInfo = "在";
			for (CityInfo cityInfo : result.getSuggestCityList()) {
				strInfo += cityInfo.city;
				strInfo += ",";
			}
			strInfo += "找到结果";
			Toast.makeText(BaiduMapActivity.this, strInfo, Toast.LENGTH_LONG)
					.show();
		}
	}

	public void onGetPoiDetailResult(PoiDetailResult result) {
		if (result.error != SearchResult.ERRORNO.NO_ERROR) {
			Toast.makeText(BaiduMapActivity.this, "抱歉，未找到结果", Toast.LENGTH_SHORT)
					.show();
		} else {
			address = result.getAddress();
			detailAddress = result.getName();
			curLoc.setText(address + detailAddress);
		}
	}

	@Override
	public void onGetSuggestionResult(SuggestionResult res) {
		if (res == null || res.getAllSuggestions() == null) {
			return;
		}
		sugAdapter.clear();
		for (SuggestionResult.SuggestionInfo info : res.getAllSuggestions()) {
			if (info.key != null)
				sugAdapter.add(info.key);
		}
		sugAdapter.notifyDataSetChanged();
	}

	private class MyPoiOverlay extends PoiOverlay {

		public MyPoiOverlay(BaiduMap baiduMap) {
			super(baiduMap);
		}

		@Override
		public boolean onPoiClick(int index) {
			super.onPoiClick(index);
			PoiInfo poi = getPoiResult().getAllPoi().get(index);
			// if (poi.hasCaterDetails) {
				mPoiSearch.searchPoiDetail((new PoiDetailSearchOption())
						.poiUid(poi.uid));
			// }
			return true;
		}
	}

	
	
	@Override
	public void onGetGeoCodeResult(GeoCodeResult result) {
		String baseAddress = curLoc.getText().toString();

		if (baseAddress == null || baseAddress.equals("")) {
			Toast.makeText(BaiduMapActivity.this, "基础地址不存在！请重新选择或输入！", Toast.LENGTH_LONG)
					.show();
			return;
		}
		Intent intent = new Intent();
		intent.putExtra("baseAddress", address);
		intent.putExtra("detailAddress", detailAddress);
		setResult(RESULT_OK, intent);
		BaiduMapActivity.this.finish();
	}
	

	@Override
	public void onGetReverseGeoCodeResult(ReverseGeoCodeResult result) {
		if (result == null || result.error != SearchResult.ERRORNO.NO_ERROR) {
			Toast.makeText(BaiduMapActivity.this, "抱歉，未能找到结果", Toast.LENGTH_LONG).show();
			return;
		}
		address = result.getAddress();
		ac = result.getAddressDetail();
		curLoc.setText(address);
	}

	@Override
	public void onBackPressed() {
		Intent intent = new Intent();
		intent.putExtra("baseAddress", "点击选取活动地址");
		intent.putExtra("detailAddress", "");
		setResult(RESULT_OK, intent);
		BaiduMapActivity.this.finish();
		return;
	}
}
